/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.plc4x.java.opcua.readwrite;

import static org.apache.plc4x.java.spi.codegen.fields.FieldReaderFactory.*;
import static org.apache.plc4x.java.spi.codegen.fields.FieldWriterFactory.*;
import static org.apache.plc4x.java.spi.codegen.io.DataReaderFactory.*;
import static org.apache.plc4x.java.spi.codegen.io.DataWriterFactory.*;
import static org.apache.plc4x.java.spi.generation.StaticHelper.*;

import java.time.*;
import java.util.*;
import org.apache.plc4x.java.api.exceptions.*;
import org.apache.plc4x.java.api.value.*;
import org.apache.plc4x.java.spi.codegen.*;
import org.apache.plc4x.java.spi.codegen.fields.*;
import org.apache.plc4x.java.spi.codegen.io.*;
import org.apache.plc4x.java.spi.generation.*;

// Code generated by code-generation. DO NOT EDIT.

public class PubSubConnectionDataType extends ExtensionObjectDefinition implements Message {

  // Accessors for discriminator values.
  public String getIdentifier() {
    return (String) "15619";
  }

  // Properties.
  protected final PascalString name;
  protected final boolean enabled;
  protected final Variant publisherId;
  protected final PascalString transportProfileUri;
  protected final ExtensionObject address;
  protected final int noOfConnectionProperties;
  protected final List<ExtensionObjectDefinition> connectionProperties;
  protected final ExtensionObject transportSettings;
  protected final int noOfWriterGroups;
  protected final List<PubSubGroupDataType> writerGroups;
  protected final int noOfReaderGroups;
  protected final List<PubSubGroupDataType> readerGroups;
  // Reserved Fields
  private Short reservedField0;

  public PubSubConnectionDataType(
      PascalString name,
      boolean enabled,
      Variant publisherId,
      PascalString transportProfileUri,
      ExtensionObject address,
      int noOfConnectionProperties,
      List<ExtensionObjectDefinition> connectionProperties,
      ExtensionObject transportSettings,
      int noOfWriterGroups,
      List<PubSubGroupDataType> writerGroups,
      int noOfReaderGroups,
      List<PubSubGroupDataType> readerGroups) {
    super();
    this.name = name;
    this.enabled = enabled;
    this.publisherId = publisherId;
    this.transportProfileUri = transportProfileUri;
    this.address = address;
    this.noOfConnectionProperties = noOfConnectionProperties;
    this.connectionProperties = connectionProperties;
    this.transportSettings = transportSettings;
    this.noOfWriterGroups = noOfWriterGroups;
    this.writerGroups = writerGroups;
    this.noOfReaderGroups = noOfReaderGroups;
    this.readerGroups = readerGroups;
  }

  public PascalString getName() {
    return name;
  }

  public boolean getEnabled() {
    return enabled;
  }

  public Variant getPublisherId() {
    return publisherId;
  }

  public PascalString getTransportProfileUri() {
    return transportProfileUri;
  }

  public ExtensionObject getAddress() {
    return address;
  }

  public int getNoOfConnectionProperties() {
    return noOfConnectionProperties;
  }

  public List<ExtensionObjectDefinition> getConnectionProperties() {
    return connectionProperties;
  }

  public ExtensionObject getTransportSettings() {
    return transportSettings;
  }

  public int getNoOfWriterGroups() {
    return noOfWriterGroups;
  }

  public List<PubSubGroupDataType> getWriterGroups() {
    return writerGroups;
  }

  public int getNoOfReaderGroups() {
    return noOfReaderGroups;
  }

  public List<PubSubGroupDataType> getReaderGroups() {
    return readerGroups;
  }

  @Override
  protected void serializeExtensionObjectDefinitionChild(WriteBuffer writeBuffer)
      throws SerializationException {
    PositionAware positionAware = writeBuffer;
    int startPos = positionAware.getPos();
    writeBuffer.pushContext("PubSubConnectionDataType");

    // Simple Field (name)
    writeSimpleField("name", name, new DataWriterComplexDefault<>(writeBuffer));

    // Reserved Field (reserved)
    writeReservedField(
        "reserved",
        reservedField0 != null ? reservedField0 : (short) 0x00,
        writeUnsignedShort(writeBuffer, 7));

    // Simple Field (enabled)
    writeSimpleField("enabled", enabled, writeBoolean(writeBuffer));

    // Simple Field (publisherId)
    writeSimpleField("publisherId", publisherId, new DataWriterComplexDefault<>(writeBuffer));

    // Simple Field (transportProfileUri)
    writeSimpleField(
        "transportProfileUri", transportProfileUri, new DataWriterComplexDefault<>(writeBuffer));

    // Simple Field (address)
    writeSimpleField("address", address, new DataWriterComplexDefault<>(writeBuffer));

    // Simple Field (noOfConnectionProperties)
    writeSimpleField(
        "noOfConnectionProperties", noOfConnectionProperties, writeSignedInt(writeBuffer, 32));

    // Array Field (connectionProperties)
    writeComplexTypeArrayField("connectionProperties", connectionProperties, writeBuffer);

    // Simple Field (transportSettings)
    writeSimpleField(
        "transportSettings", transportSettings, new DataWriterComplexDefault<>(writeBuffer));

    // Simple Field (noOfWriterGroups)
    writeSimpleField("noOfWriterGroups", noOfWriterGroups, writeSignedInt(writeBuffer, 32));

    // Array Field (writerGroups)
    writeComplexTypeArrayField("writerGroups", writerGroups, writeBuffer);

    // Simple Field (noOfReaderGroups)
    writeSimpleField("noOfReaderGroups", noOfReaderGroups, writeSignedInt(writeBuffer, 32));

    // Array Field (readerGroups)
    writeComplexTypeArrayField("readerGroups", readerGroups, writeBuffer);

    writeBuffer.popContext("PubSubConnectionDataType");
  }

  @Override
  public int getLengthInBytes() {
    return (int) Math.ceil((float) getLengthInBits() / 8.0);
  }

  @Override
  public int getLengthInBits() {
    int lengthInBits = super.getLengthInBits();
    PubSubConnectionDataType _value = this;

    // Simple field (name)
    lengthInBits += name.getLengthInBits();

    // Reserved Field (reserved)
    lengthInBits += 7;

    // Simple field (enabled)
    lengthInBits += 1;

    // Simple field (publisherId)
    lengthInBits += publisherId.getLengthInBits();

    // Simple field (transportProfileUri)
    lengthInBits += transportProfileUri.getLengthInBits();

    // Simple field (address)
    lengthInBits += address.getLengthInBits();

    // Simple field (noOfConnectionProperties)
    lengthInBits += 32;

    // Array field
    if (connectionProperties != null) {
      int i = 0;
      for (ExtensionObjectDefinition element : connectionProperties) {
        boolean last = ++i >= connectionProperties.size();
        lengthInBits += element.getLengthInBits();
      }
    }

    // Simple field (transportSettings)
    lengthInBits += transportSettings.getLengthInBits();

    // Simple field (noOfWriterGroups)
    lengthInBits += 32;

    // Array field
    if (writerGroups != null) {
      int i = 0;
      for (PubSubGroupDataType element : writerGroups) {
        boolean last = ++i >= writerGroups.size();
        lengthInBits += element.getLengthInBits();
      }
    }

    // Simple field (noOfReaderGroups)
    lengthInBits += 32;

    // Array field
    if (readerGroups != null) {
      int i = 0;
      for (PubSubGroupDataType element : readerGroups) {
        boolean last = ++i >= readerGroups.size();
        lengthInBits += element.getLengthInBits();
      }
    }

    return lengthInBits;
  }

  public static PubSubConnectionDataTypeBuilder staticParseBuilder(
      ReadBuffer readBuffer, String identifier) throws ParseException {
    readBuffer.pullContext("PubSubConnectionDataType");
    PositionAware positionAware = readBuffer;
    int startPos = positionAware.getPos();
    int curPos;

    PascalString name =
        readSimpleField(
            "name",
            new DataReaderComplexDefault<>(() -> PascalString.staticParse(readBuffer), readBuffer));

    Short reservedField0 =
        readReservedField("reserved", readUnsignedShort(readBuffer, 7), (short) 0x00);

    boolean enabled = readSimpleField("enabled", readBoolean(readBuffer));

    Variant publisherId =
        readSimpleField(
            "publisherId",
            new DataReaderComplexDefault<>(() -> Variant.staticParse(readBuffer), readBuffer));

    PascalString transportProfileUri =
        readSimpleField(
            "transportProfileUri",
            new DataReaderComplexDefault<>(() -> PascalString.staticParse(readBuffer), readBuffer));

    ExtensionObject address =
        readSimpleField(
            "address",
            new DataReaderComplexDefault<>(
                () -> ExtensionObject.staticParse(readBuffer, (boolean) (true)), readBuffer));

    int noOfConnectionProperties =
        readSimpleField("noOfConnectionProperties", readSignedInt(readBuffer, 32));

    List<ExtensionObjectDefinition> connectionProperties =
        readCountArrayField(
            "connectionProperties",
            new DataReaderComplexDefault<>(
                () -> ExtensionObjectDefinition.staticParse(readBuffer, (String) ("14535")),
                readBuffer),
            noOfConnectionProperties);

    ExtensionObject transportSettings =
        readSimpleField(
            "transportSettings",
            new DataReaderComplexDefault<>(
                () -> ExtensionObject.staticParse(readBuffer, (boolean) (true)), readBuffer));

    int noOfWriterGroups = readSimpleField("noOfWriterGroups", readSignedInt(readBuffer, 32));

    List<PubSubGroupDataType> writerGroups =
        readCountArrayField(
            "writerGroups",
            new DataReaderComplexDefault<>(
                () ->
                    (PubSubGroupDataType)
                        ExtensionObjectDefinition.staticParse(readBuffer, (String) ("15609")),
                readBuffer),
            noOfWriterGroups);

    int noOfReaderGroups = readSimpleField("noOfReaderGroups", readSignedInt(readBuffer, 32));

    List<PubSubGroupDataType> readerGroups =
        readCountArrayField(
            "readerGroups",
            new DataReaderComplexDefault<>(
                () ->
                    (PubSubGroupDataType)
                        ExtensionObjectDefinition.staticParse(readBuffer, (String) ("15609")),
                readBuffer),
            noOfReaderGroups);

    readBuffer.closeContext("PubSubConnectionDataType");
    // Create the instance
    return new PubSubConnectionDataTypeBuilder(
        name,
        enabled,
        publisherId,
        transportProfileUri,
        address,
        noOfConnectionProperties,
        connectionProperties,
        transportSettings,
        noOfWriterGroups,
        writerGroups,
        noOfReaderGroups,
        readerGroups,
        reservedField0);
  }

  public static class PubSubConnectionDataTypeBuilder
      implements ExtensionObjectDefinition.ExtensionObjectDefinitionBuilder {
    private final PascalString name;
    private final boolean enabled;
    private final Variant publisherId;
    private final PascalString transportProfileUri;
    private final ExtensionObject address;
    private final int noOfConnectionProperties;
    private final List<ExtensionObjectDefinition> connectionProperties;
    private final ExtensionObject transportSettings;
    private final int noOfWriterGroups;
    private final List<PubSubGroupDataType> writerGroups;
    private final int noOfReaderGroups;
    private final List<PubSubGroupDataType> readerGroups;
    private final Short reservedField0;

    public PubSubConnectionDataTypeBuilder(
        PascalString name,
        boolean enabled,
        Variant publisherId,
        PascalString transportProfileUri,
        ExtensionObject address,
        int noOfConnectionProperties,
        List<ExtensionObjectDefinition> connectionProperties,
        ExtensionObject transportSettings,
        int noOfWriterGroups,
        List<PubSubGroupDataType> writerGroups,
        int noOfReaderGroups,
        List<PubSubGroupDataType> readerGroups,
        Short reservedField0) {
      this.name = name;
      this.enabled = enabled;
      this.publisherId = publisherId;
      this.transportProfileUri = transportProfileUri;
      this.address = address;
      this.noOfConnectionProperties = noOfConnectionProperties;
      this.connectionProperties = connectionProperties;
      this.transportSettings = transportSettings;
      this.noOfWriterGroups = noOfWriterGroups;
      this.writerGroups = writerGroups;
      this.noOfReaderGroups = noOfReaderGroups;
      this.readerGroups = readerGroups;
      this.reservedField0 = reservedField0;
    }

    public PubSubConnectionDataType build() {
      PubSubConnectionDataType pubSubConnectionDataType =
          new PubSubConnectionDataType(
              name,
              enabled,
              publisherId,
              transportProfileUri,
              address,
              noOfConnectionProperties,
              connectionProperties,
              transportSettings,
              noOfWriterGroups,
              writerGroups,
              noOfReaderGroups,
              readerGroups);
      pubSubConnectionDataType.reservedField0 = reservedField0;
      return pubSubConnectionDataType;
    }
  }

  @Override
  public boolean equals(Object o) {
    if (this == o) {
      return true;
    }
    if (!(o instanceof PubSubConnectionDataType)) {
      return false;
    }
    PubSubConnectionDataType that = (PubSubConnectionDataType) o;
    return (getName() == that.getName())
        && (getEnabled() == that.getEnabled())
        && (getPublisherId() == that.getPublisherId())
        && (getTransportProfileUri() == that.getTransportProfileUri())
        && (getAddress() == that.getAddress())
        && (getNoOfConnectionProperties() == that.getNoOfConnectionProperties())
        && (getConnectionProperties() == that.getConnectionProperties())
        && (getTransportSettings() == that.getTransportSettings())
        && (getNoOfWriterGroups() == that.getNoOfWriterGroups())
        && (getWriterGroups() == that.getWriterGroups())
        && (getNoOfReaderGroups() == that.getNoOfReaderGroups())
        && (getReaderGroups() == that.getReaderGroups())
        && super.equals(that)
        && true;
  }

  @Override
  public int hashCode() {
    return Objects.hash(
        super.hashCode(),
        getName(),
        getEnabled(),
        getPublisherId(),
        getTransportProfileUri(),
        getAddress(),
        getNoOfConnectionProperties(),
        getConnectionProperties(),
        getTransportSettings(),
        getNoOfWriterGroups(),
        getWriterGroups(),
        getNoOfReaderGroups(),
        getReaderGroups());
  }

  @Override
  public String toString() {
    WriteBufferBoxBased writeBufferBoxBased = new WriteBufferBoxBased(true, true);
    try {
      writeBufferBoxBased.writeSerializable(this);
    } catch (SerializationException e) {
      throw new RuntimeException(e);
    }
    return "\n" + writeBufferBoxBased.getBox().toString() + "\n";
  }
}
